// -----------------------------------------------------------------------------
// M A R I T I M E   R E S E A R C H   I N S T I T U T E   N E T H E R L A N D S
// -----------------------------------------------------------------------------
// Copyright (C) February 1, 2010 MARIN - All rights reserved - http://www.marin.nl
// -----------------------------------------------------------------------------
// Program  : mermaid
// Module   : vbm
// File     : Timer.cpp
// -----------------------------------------------------------------------------
#include <cstddef>

#if !defined(nullptr)
#define nullptr NULL
#endif


#include <new>

#include "Timer.h"

#ifndef _WINDOWS

#include <sys/time.h> // gettimeofday

#else // _WINDOWS

// http://www.cpp-programming.net/c-tidbits/gettimeofday-function-for-windows/
#include <time.h>
#include <windows.h>

#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
#else
#define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
#endif

#pragma warning(disable: 4996) // '__timezone': This function or variable may be unsafe.

///
struct timezone
{
    int tz_minuteswest; /* minutes W of Greenwich */
    int tz_dsttime; /* type of dst correction */
};


/// windows equivalent of unix function
static int gettimeofday(struct timeval *tv, struct timezone *tz)
{
    FILETIME ft;
    unsigned __int64 tmpres = 0;
    static int tzflag = 0;

    if (NULL != tv)
    {
        GetSystemTimeAsFileTime(&ft);

        tmpres |= ft.dwHighDateTime;
        tmpres <<= 32;
        tmpres |= ft.dwLowDateTime;

        tmpres /= 10; /*convert into microseconds*/
        /*converting file time to unix epoch*/
        tmpres -= DELTA_EPOCH_IN_MICROSECS;
        tv->tv_sec = (long)(tmpres / 1000000UL);
        tv->tv_usec = (long)(tmpres % 1000000UL);
    }

    if (NULL != tz)
    {
        if (!tzflag)
        {
            _tzset();
            tzflag++;
        }
        tz->tz_minuteswest = _timezone / 60;
        tz->tz_dsttime = _daylight;
    }

    return 0;
}

#endif // _WINDOWS

// -----------------------------------------------------------------------------
// function Timer::Timer
// -----------------------------------------------------------------------------
/// constructor
/** detailed description */
// -----------------------------------------------------------------------------
Timer::Timer()
    : m_start(0)
{
    timeval tim;

    gettimeofday(&tim, NULL);
    m_start = tim.tv_sec + (tim.tv_usec / 1000000.0);
}


// -----------------------------------------------------------------------------
// function Timer::~Timer()
// -----------------------------------------------------------------------------
/// destructor
/** detailed description */
// -----------------------------------------------------------------------------
Timer::~Timer()
{
    // implementation
}


// -----------------------------------------------------------------------------
// function double GetElapsedTime()
// -----------------------------------------------------------------------------
/// @return elapsed time in seconds
// -----------------------------------------------------------------------------
double Timer::getElapsedTime()
{
    timeval tim;
    gettimeofday(&tim, NULL);
    return tim.tv_sec + (tim.tv_usec / 1000000.0) - m_start;
}


// -----------------------------------------------------------------------------
